package com.falm.picturebackend.util;

import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 */
@Component
public class MinioUtil {

    @Value("${minio.endpoint:http://120.76.230.142:9000}")
    private String minioEndpoint;

    @Value("${minio.accessKey:minioadmin}")
    private String minioAccessKey;

    @Value("${minio.secretKey:minioadmin}")
    private String minioSecretKey;

    @Value("${minio.bucketName:picture}")
    private String bucketName;

    private MinioClient minioClient;

    // 初始化MinioClient
    private MinioClient getMinioClient() {
        if (minioClient == null) {
            minioClient =
                MinioClient.builder().endpoint(minioEndpoint).credentials(minioAccessKey, minioSecretKey).build();
        }
        return minioClient;
    }

    /**
     * 上传文件
     *
     * @param file 要上传的文件
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return uploadFile(file, file.getOriginalFilename());
    }

    /**
     * 上传文件（指定文件名）
     *
     * @param file 要上传的文件
     * @param fileName 文件名
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file, String fileName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        InputStream inputStream = file.getInputStream();
        getMinioClient().putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName)
            .stream(inputStream, inputStream.available(), -1).contentType(file.getContentType()).build());
        return getFileUrl(fileName);
    }

    /**
     * 删除文件
     *
     * @param fileName 文件名
     */
    public void deleteFile(String fileName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        getMinioClient().removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
    }

    /**
     * 获取文件访问URL
     *
     * @param fileName 文件名
     * @return 文件访问URL
     */
    public String getFileUrl(String fileName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return getMinioClient().getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET)
            .bucket(bucketName).object(fileName).expiry(7, TimeUnit.DAYS).build());
    }

    /**
     * 下载文件
     *
     * @param fileName 文件名
     * @return 文件输入流
     */
    public InputStream downloadFile(String fileName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return getMinioClient().getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
    }

    /**
     * 判断文件是否存在
     *
     * @param fileName 文件名
     * @return 文件是否存在
     */
    public boolean doesFileExist(String fileName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        try {
            getMinioClient().statObject(StatObjectArgs.builder().bucket(bucketName).object(fileName).build());
            return true;
        } catch (ErrorResponseException e) {
            if ("NoSuchKey".equals(e.errorResponse().code())) {
                return false;
            }
            throw e;
        }
    }

    /**
     * 获取文件信息
     *
     * @param fileName 文件名
     * @return 文件信息
     */
    public StatObjectResponse getFileInfo(String fileName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return getMinioClient().statObject(StatObjectArgs.builder().bucket(bucketName).object(fileName).build());
    }

    /**
     * 创建存储桶
     *
     * @param bucketName 存储桶名称
     */
    public void createBucket(String bucketName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        boolean exists = getMinioClient().bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!exists) {
            getMinioClient().makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 删除存储桶
     *
     * @param bucketName 存储桶名称
     */
    public void deleteBucket(String bucketName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        getMinioClient().removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 判断存储桶是否存在
     *
     * @param bucketName 存储桶名称
     * @return 存储桶是否存在
     */
    public boolean doesBucketExist(String bucketName)
        throws ServerException, InsufficientDataException, ErrorResponseException, IOException,
        NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return getMinioClient().bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }
}